"""
Récupération des identifiants Accès Libre via l'API DATAtourisme
Export complet (CSV + Excel + JSON)
"""
# Créé par Anjou Tourisme Attractivité
# Annabelle ALLARD — annabelle-allard@anjou-tourisme.com

import requests
import json
import csv
import time
import re
import openpyxl
from datetime import date

# ══════════════════════════════════════════════════════════════
# ⚙️  CONFIGURATION — champs à personnaliser avant de lancer
# ══════════════════════════════════════════════════════════════

# 🔑 Votre clé API DATAtourisme (fournie lors de votre inscription)
API_KEY = "VOTRE-CLÉ-API-ICI"

# 🗺️  Filtre géographique
# Pour un département  : insee[eq]=XX
# Pour plusieurs       : insee[in]=XX,YY,ZZ
# Exemples : [eq]=49 (Maine-et-Loire), [in]=44,49,53,72,85 (Pays de la Loire)
FILTER_EXPR = (
    "hasExternalReference.hasExternalPlatform.hasExternalPlatformUrl[eq]=https://acceslibre.beta.gouv.fr"
    " AND "
    "isLocatedAt.address.hasAddressCity.isPartOfDepartment.insee[eq]=XX"
)

# ══════════════════════════════════════════════════════════════
# ⛔  Ne pas modifier en dessous de cette ligne
# ══════════════════════════════════════════════════════════════

BASE_URL  = "https://api.datatourisme.fr/v1"
PAGE_SIZE = 250
PAUSE     = 0.15

DATE_PREFIX = date.today().strftime("%Y%m%d")

match = re.search(r"isPartOfDepartment\.insee\[(?:eq|in)\]=([0-9,]+)", FILTER_EXPR)
ZONE = match.group(1).replace(",", "-") if match else "inconnu"

OUTPUT_JSON  = f"{DATE_PREFIX}-AccesLibre-complet-{ZONE}.json"
OUTPUT_CSV   = f"{DATE_PREFIX}-AccesLibre-complet-{ZONE}.csv"
OUTPUT_EXCEL = f"{DATE_PREFIX}-AccesLibre-complet-{ZONE}.xlsx"

FIELDS = ",".join([
    "uuid",
    "uri",
    "label",
    "identifier",
    "hasExternalReference",
    "hasBeenCreatedBy",
    "isLocatedAt.address.hasAddressCity",
    "isLocatedAt.address.hasAddressCity.isPartOfDepartment",
])

HEADERS = {"X-API-Key": API_KEY, "Accept": "application/json"}

# ── Helpers ───────────────────────────────────────────────────────────────────

def extract_acceslibre_id(refs) -> str | None:
    if not isinstance(refs, list):
        refs = [refs]
    for ref in refs:
        if not isinstance(ref, dict):
            continue
        platform = ref.get("hasExternalPlatform", [])
        if isinstance(platform, list):
            platform = platform[0] if platform else {}
        url = platform.get("hasExternalPlatformUrl", "")
        if "acceslibre" in url.lower():
            return ref.get("hasExternalIdentifier")
    return None


def extract_label(poi: dict) -> str:
    label = poi.get("label", {})
    if isinstance(label, dict):
        return label.get("@fr") or label.get("@en") or next(iter(label.values()), "")
    return str(label) if label else ""


def extract_commune_label(poi: dict) -> str:
    try:
        locations = poi.get("isLocatedAt", [])
        if not isinstance(locations, list):
            locations = [locations]
        address = locations[0]["address"]
        if isinstance(address, list):
            address = address[0]
        city = address["hasAddressCity"]
        if isinstance(city, dict):
            nom = city.get("label", {})
            if isinstance(nom, dict):
                return nom.get("@fr") or nom.get("@en", "")
            return str(nom)
    except (KeyError, IndexError, TypeError):
        pass
    return ""


def extract_commune_insee(poi: dict) -> str:
    try:
        locations = poi.get("isLocatedAt", [])
        if not isinstance(locations, list):
            locations = [locations]
        address = locations[0]["address"]
        if isinstance(address, list):
            address = address[0]
        city = address["hasAddressCity"]
        if isinstance(city, dict):
            return city.get("insee", "")
    except (KeyError, IndexError, TypeError):
        pass
    return ""


def extract_departement(poi: dict) -> str:
    try:
        locations = poi.get("isLocatedAt", [])
        if not isinstance(locations, list):
            locations = [locations]
        address = locations[0]["address"]
        if isinstance(address, list):
            address = address[0]
        dept = address["hasAddressCity"]["isPartOfDepartment"]
        if isinstance(dept, list):
            dept = dept[0] if dept else {}
        return dept.get("insee", "")
    except (KeyError, IndexError, TypeError):
        pass
    return ""


def extract_legal_name(poi: dict) -> str:
    try:
        created_by = poi.get("hasBeenCreatedBy", {})
        if isinstance(created_by, list):
            created_by = created_by[0] if created_by else {}
        return created_by.get("legalName", "")
    except (KeyError, IndexError, TypeError):
        pass
    return ""


def build_widget(acceslibre_id: str) -> str:
    return (
        f'<div id="widget-a11y-container" data-pk="{acceslibre_id}" data-baseurl="https://acceslibre.beta.gouv.fr"></div> '
        f'<a href="#" aria-haspopup="dialog" data-erp-pk="{acceslibre_id}" aria-controls="dialog" data-owner="acceslibre">Accessibilité</a> '
        f'<script src="https://acceslibre.beta.gouv.fr/static/js/widget.js" type="text/javascript" async="true"></script>'
    )

# ── Appels API ────────────────────────────────────────────────────────────────

def fetch_page(url: str, params: dict | None = None) -> dict:
    resp = requests.get(url, headers=HEADERS, params=params, timeout=30)
    resp.raise_for_status()
    return resp.json()


def fetch_all() -> list[dict]:
    params = {
        "api_key":   API_KEY,
        "fields":    FIELDS,
        "filters":   FILTER_EXPR,
        "page_size": PAGE_SIZE,
        "page":      1,
    }

    results  = []
    url      = f"{BASE_URL}/catalog"
    page_num = 0

    while url:
        page_num += 1
        print(f"  Page {page_num}…", end=" ", flush=True)

        data    = fetch_page(url, params if page_num == 1 else None)
        objects = data.get("objects", [])
        meta    = data.get("meta", {})

        if page_num == 1:
            print(f"(total : {meta.get('total', '?')} POIs, {meta.get('total_pages', '?')} pages)")

        for poi in objects:
            acceslibre_id = extract_acceslibre_id(poi.get("hasExternalReference", []))
            if acceslibre_id:
                results.append({
                    "identifier":         poi.get("identifier", ""),
                    "label":              extract_label(poi),
                    "code_insee_commune": extract_commune_insee(poi),
                    "commune":            extract_commune_label(poi),
                    "departement_insee":  extract_departement(poi),
                    "datatourisme_uuid":  poi.get("uuid", ""),
                    "datatourisme_uri":   poi.get("uri", ""),
                    "acceslibre_id":      acceslibre_id,
                    "acceslibre_url":     f"https://acceslibre.beta.gouv.fr/uuid/{acceslibre_id}/",
                    "acceslibre_widget":  build_widget(acceslibre_id),
                    "producteur":         extract_legal_name(poi),
                })

        print(f"    → {len(results)} trouvés jusqu'ici")

        url = meta.get("next")
        if url:
            time.sleep(PAUSE)

    results.sort(key=lambda x: x["identifier"].lower())
    return results

# ── Export ────────────────────────────────────────────────────────────────────

def save_json(data: list[dict], path: str) -> None:
    export = {
        "metadata": {
            "source":    "Accès Libre × DATAtourisme",
            "createur":  "Annabelle ALLARD",
            "structure": "Anjou Tourisme Attractivité",
            "contact":   "annabelle-allard@anjou-tourisme.com",
            "date":      date.today().strftime("%d/%m/%Y"),
            "zone":      ZONE,
        },
        "data": data
    }
    with open(path, "w", encoding="utf-8") as f:
        json.dump(export, f, ensure_ascii=False, indent=2)

def save_csv(data: list[dict], path: str) -> None:
    if not data:
        return
    with open(path, "w", encoding="utf-8-sig", newline="") as f:
        writer = csv.DictWriter(f, fieldnames=data[0].keys(), delimiter=";", quoting=csv.QUOTE_MINIMAL)
        writer.writeheader()
        writer.writerows(data)
    print(f"✓ CSV   : {path} ({len(data)} entrées)")


def save_excel(data: list[dict], path: str) -> None:
    if not data:
        return
    wb = openpyxl.Workbook()
    ws = wb.active
    ws.title = f"Accès Libre {ZONE}"
    headers = list(data[0].keys())
    for col_idx, header in enumerate(headers, start=1):
        cell = ws.cell(row=1, column=col_idx, value=header)
        cell.font = openpyxl.styles.Font(bold=True)
    for row_idx, row in enumerate(data, start=2):
        for col_idx, key in enumerate(headers, start=1):
            ws.cell(row=row_idx, column=col_idx, value=row[key])
    for col in ws.columns:
        max_length = max(len(str(cell.value or "")) for cell in col)
        ws.column_dimensions[col[0].column_letter].width = min(max_length + 2, 60)
    wb.properties.creator = "Annabelle ALLARD"
    wb.properties.company = "Anjou Tourisme Attractivité"
    wb.properties.description = "Export Accès Libre × DATAtourisme — annabelle-allard@anjou-tourisme.com"
    wb.save(path)
    print(f"✓ Excel : {path} ({len(data)} entrées)")

# ── Main ──────────────────────────────────────────────────────────────────────

if __name__ == "__main__":
    print("=" * 60)
    print(f"Récupération des IDs Accès Libre — zone : {ZONE}")
    print("Source : API DATAtourisme v1")
    print("=" * 60)

    try:
        poi_list = fetch_all()

        print(f"\n{'='*60}")
        print(f"Résultat final : {len(poi_list)} POI(s) avec un ID Accès Libre")

        if poi_list:
            print()
            save_json(poi_list,  OUTPUT_JSON)
            save_csv(poi_list,   OUTPUT_CSV)
            save_excel(poi_list, OUTPUT_EXCEL)

            try:
                from google.colab import files
                files.download(OUTPUT_JSON)
                files.download(OUTPUT_CSV)
                files.download(OUTPUT_EXCEL)
            except ImportError:
                pass
        else:
            print("\nAucun résultat.")

    except requests.HTTPError as e:
        print(f"\n✗ Erreur HTTP : {e}")
    except KeyboardInterrupt:
        print("\n✗ Interrompu.")